package br.dcc.ufmg.controller;

import java.io.File;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;

import javax.swing.JFileChooser;
import javax.swing.JOptionPane;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.filechooser.FileFilter;

import br.dcc.ufmg.domain.Class;
import br.dcc.ufmg.domain.Method;
import br.dcc.ufmg.domain.Package;
import br.dcc.ufmg.filtering.impl.ClassesFilter;
import br.dcc.ufmg.filtering.impl.MethodsFilter;
import br.dcc.ufmg.filtering.impl.PackagesFilter;
import br.dcc.ufmg.persistence.HSQLDBConnection;
import br.dcc.ufmg.view.FilterJFrame;
import br.dcc.ufmg.xml.XmlFileToDatabase;

public class FilterController {

	private final FilterJFrame frame = new FilterJFrame(this);

	private Set<File> xmlFiles = new LinkedHashSet<File>();

	public void btnXMLFilesSelectionActionPerformed(
			java.awt.event.ActionEvent evt) {// GEN-FIRST:event_btnXMLFilesSelectionActionPerformed
		frame.getFileChooser().setFileFilter(new FileFilter() {
			@Override
			public boolean accept(File file) {
				return file.getAbsolutePath().endsWith(".xml")
						|| file.isDirectory();
			}

			@Override
			public String getDescription() {
				return "Only XML files are accepted.";
			}
		});
		int returnVal = frame.getFileChooser().showOpenDialog(frame);
		if (returnVal == JFileChooser.APPROVE_OPTION) {
			File[] selectedXmlFiles = frame.getFileChooser().getSelectedFiles();
			for (File xml : selectedXmlFiles) {
				if (this.xmlFiles.add(xml)) {
					String preText = frame.getTxtAreaFilesSelected().getText();
					preText = (preText != null && !preText.equals("")) ? (preText + "\n")
							: "";
					frame.getTxtAreaFilesSelected().setText(
							preText + xml.getName());
				}
				frame.getBtnDoneSelection().setEnabled(true);
			}
		}
	}// GEN-LAST:event_btnXMLFilesSelectionActionPerformed

	public boolean evaluateFilters() {
		boolean valid = true;
		if (frame.getTxtAreaBooleanExpression().getText().equals("")) {
			JOptionPane.showMessageDialog(null,
					"Filter Expression must not be empty.", "Error",
					JOptionPane.ERROR_MESSAGE);
			valid = false;
		}
		return valid;
	}

	public void btnFilterExecutionActionPerformed(java.awt.event.ActionEvent evt) {// GEN-FIRST:event_btnFilterExecutionActionPerformed
		if (evaluateFilters()) {
			try {
				final FilterResultController resultController = new FilterResultController();
				switch (frame.getBoxArtifactType().getSelectedItem().toString()) {
				case "Method":
					MethodsFilter m = new MethodsFilter(frame
							.getTxtSystemName().getText(), frame
							.getTxtAreaBooleanExpression().getText(), frame
							.getTxtFieldOrder().getText().equals("") ? null
							: frame.getTxtFieldOrder().getText());
					List<Method> methods = m.filter();
					resultController.populateTableMethods(methods, m.getTotalArtifactsBeforeFiltering());
					break;
				case "Class": {
					ClassesFilter c = new ClassesFilter(frame
							.getTxtSystemName().getText(), frame
							.getTxtAreaBooleanExpression().getText(), frame
							.getTxtFieldOrder().getText().equals("") ? null
							: frame.getTxtFieldOrder().getText());
					List<Class> classes = c.filter();
					resultController.populateTableClasses(classes, c.getTotalArtifactsBeforeFiltering());
					break;
				}
				case "Package": {
					PackagesFilter p = new PackagesFilter(frame
							.getTxtSystemName().getText(), frame
							.getTxtAreaBooleanExpression().getText(), frame
							.getTxtFieldOrder().getText().equals("") ? null
							: frame.getTxtFieldOrder().getText());
					List<Package> packages = p.filter();
					resultController.populateTablePackages(packages, p.getTotalArtifactsBeforeFiltering());
					break;
				}
				}
				resultController.getFrame().setVisible(true);
			} catch (Exception ex) {
				Logger.getLogger(FilterJFrame.class.getName()).log(
						Level.SEVERE, null, ex);
			}
		}
	}// GEN-LAST:event_btnFilterExecutionActionPerformed

	public void taskFieldsFilesSelection(boolean task) {
		frame.getTxtAreaFilesSelected().setEnabled(task);
		frame.getBtnXMLFilesSelection().setEnabled(task);
		frame.getTxtSystemName().setEnabled(task);
		frame.getBtnDoneSelection().setEnabled(task);
	}

	public void taskFieldsFilteringProcess(boolean task) {
		frame.getTxtAreaBooleanExpression().setEnabled(task);
		frame.getBoxArtifactType().setEnabled(task);
		frame.getTxtFieldOrder().setEnabled(task);
		frame.getBtnFilterExecution().setEnabled(task);
		frame.getBtnReset().setEnabled(task);
	}

	public boolean evaluateXMLFilesSelection() {
		boolean valid = !frame.getTxtSystemName().getText().equals("");
		if (!valid) {
			JOptionPane.showMessageDialog(null,
					"System name must not be empty.", "Error",
					JOptionPane.ERROR_MESSAGE);
		}
		return valid;
	}

	public void btnDoneSelectionActionPerformed(java.awt.event.ActionEvent evt) {// GEN-FIRST:event_frame.getBtnDoneSelection()ActionPerformed
		if (evaluateXMLFilesSelection()) {
			try {
				taskFieldsFilesSelection(false);
				taskFieldsFilteringProcess(true);
				for (File xmlFile : xmlFiles) {
					XmlFileToDatabase xmlFileToDatabase = new XmlFileToDatabase(
							xmlFile);
					xmlFileToDatabase.importFileToDatabase(frame
							.getTxtSystemName().getText());
				}
			} catch (Exception ex) {
				Logger.getLogger(FilterJFrame.class.getName()).log(
						Level.SEVERE, null, ex);
			}
		}
	}

	public void btnResetActionPerformed(java.awt.event.ActionEvent evt) {
		frame.getTxtAreaFilesSelected().setText("");
		frame.getTxtSystemName().setText("");
		frame.getTxtAreaBooleanExpression().setText("");
		frame.getTxtFieldOrder().setText("");
		frame.getBoxArtifactType().setSelectedIndex(0);
		HSQLDBConnection.resetDatabase();
		taskFieldsFilesSelection(true);
		taskFieldsFilteringProcess(false);
	}

	public static void main(String args[]) {
		final FilterController controller = new FilterController();
		try {
			for (javax.swing.UIManager.LookAndFeelInfo info : javax.swing.UIManager
					.getInstalledLookAndFeels()) {
				if ("Nimbus".equals(info.getName())) {
					javax.swing.UIManager.setLookAndFeel(info.getClassName());
					break;
				}
			}
		} catch (ClassNotFoundException | InstantiationException
				| IllegalAccessException | UnsupportedLookAndFeelException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		java.awt.EventQueue.invokeLater(new Runnable() {
			public void run() {
				controller.frame.setVisible(true);
			}
		});
	}

	public Set<File> getXmlFiles() {
		return xmlFiles;
	}

	public void setXmlFiles(Set<File> xmlFiles) {
		this.xmlFiles = xmlFiles;
	}

}
